#include "Game.h"
#include <strsafe.h>
// Game states
#include "Pause.h"
#include "Play.h"

Game::Game(HINSTANCE hInstance, int nShowCmd)
  : Core(hInstance, nShowCmd),
  stateMachine(this)
{
	// Initialise managers
	EntityManager::init();
	MessageHandler::init();
	AnimationPlayer::AnimationPlayer();
	ForceRegistry::init();
	// Add game states
	stateMachine.addState("Pause", new Pause());
	stateMachine.addState("Play", new Play());
	stateMachine.changeState("Play");

	// CONSTRUCT STUFF...
}

Game::~Game()
{


}

void Game::initialise()
{
	// INITIALISE STUFF...
}

void Game::loadContent()
{
	// LOAD STUFF...

	//set positions for nodes
	//for player
	nodePositions[0] = D3DXVECTOR3(250, 200, 0);

	//for nutral
	nodePositions[1] = D3DXVECTOR3(500, 200, 0);
	nodePositions[2] = D3DXVECTOR3(500, 400, 0);
	nodePositions[3] = D3DXVECTOR3(700, 200, 0);

	//for finish
	nodePositions[4] = D3DXVECTOR3(700, 400, 0);


	//for opponent
	nodePositions[5] = D3DXVECTOR3(700, 50, 0);




	//Set up player node
	{
		// Create player animation pointer
		tmp[0] = new AnimationPlayer();
	
		// Load player idle texture
		D3DXCreateTextureFromFileEx(device, L"playerBaseIdleAnim.png",
			D3DX_DEFAULT_NONPOW2, D3DX_DEFAULT_NONPOW2,
			0, 0, D3DFMT_FROM_FILE, D3DPOOL_DEFAULT,
			D3DX_DEFAULT, D3DX_DEFAULT,
			0, 0, 0, &playerBaseIdleAnim);


		// Create animation from texture & set attributes
		Animation* playerIdle = new Animation(playerBaseIdleAnim);
		// Add amination to anims
		tmp[0]->addAnimation("playerBaseIdleAnim", playerIdle);
		
		//playerBaseActiveAnim
		D3DXCreateTextureFromFileEx(device, L"playerBaseActiveAnim.png",
			D3DX_DEFAULT_NONPOW2, D3DX_DEFAULT_NONPOW2,
			0, 0, D3DFMT_FROM_FILE, D3DPOOL_DEFAULT,
			D3DX_DEFAULT, D3DX_DEFAULT,
			0, 0, 0, &playerBaseActiveAnim);


		// Create animation from texture & set attributes
		Animation* playerActive = new Animation(playerBaseActiveAnim);
		// Add amination to anims
		tmp[0]->addAnimation("playerBaseActiveAnim", playerActive);

		node[0] = new Node(tmp[0], nodePositions[0], Node::PLAYER);

	}

	//Set up neutral nodes
	int limit = ALLNODES -2;
	for(int i = 1; i < limit ; i++)
	{
		// Create player animation pointer
		tmp[i] = new AnimationPlayer();
	
		// Load player nutralNodeAnim texture
		D3DXCreateTextureFromFileEx(device, L"nutralNodeAnim.png",
			D3DX_DEFAULT_NONPOW2, D3DX_DEFAULT_NONPOW2,
			0, 0, D3DFMT_FROM_FILE, D3DPOOL_DEFAULT,
			D3DX_DEFAULT, D3DX_DEFAULT,
			0, 0, 0, &nutralNodeAnim[i-1]);


		// Create animation from texture & set attributes
		Animation* nutralNode = new Animation(nutralNodeAnim[i-1]);
		// Add amination to anims
		tmp[i]->addAnimation("nutralNodeAnim", nutralNode);
		
		//secured
		D3DXCreateTextureFromFileEx(device, L"securedNodeAnim.png",
			D3DX_DEFAULT_NONPOW2, D3DX_DEFAULT_NONPOW2,
			0, 0, D3DFMT_FROM_FILE, D3DPOOL_DEFAULT,
			D3DX_DEFAULT, D3DX_DEFAULT,
			0, 0, 0, &securedNodeAnim[i-1]);


		// Create animation from texture & set attributes
		Animation* securedNode = new Animation(securedNodeAnim[i-1]);
		// Add amination to anims
		tmp[i]->addAnimation("securedNodeAnim", securedNode);
		
		//hackedNodeAnim
		D3DXCreateTextureFromFileEx(device, L"hackedNodeAnim.png",
			D3DX_DEFAULT_NONPOW2, D3DX_DEFAULT_NONPOW2,
			0, 0, D3DFMT_FROM_FILE, D3DPOOL_DEFAULT,
			D3DX_DEFAULT, D3DX_DEFAULT,
			0, 0, 0, &hackedNodeAnim[i-1]);


		// Create animation from texture & set attributes
		Animation* hackedNode = new Animation(hackedNodeAnim[i-1]);
		// Add amination to anims
		tmp[i]->addAnimation("hackedNodeAnim", hackedNode);
		
		
		//hackingSecuredNodeAnim
		D3DXCreateTextureFromFileEx(device, L"hackingSecuredNodeAnim.png",
			D3DX_DEFAULT_NONPOW2, D3DX_DEFAULT_NONPOW2,
			0, 0, D3DFMT_FROM_FILE, D3DPOOL_DEFAULT,
			D3DX_DEFAULT, D3DX_DEFAULT,
			0, 0, 0, &hackingSecuredNodeAnim[i-1]);


		// Create animation from texture & set attributes
		Animation* hackingSecuredNode = new Animation(hackingSecuredNodeAnim[i-1]);
		// Add amination to anims
		tmp[i]->addAnimation("hackingSecuredNodeAnim", hackingSecuredNode);
		
		
		//secureHackedNodeAnim
		D3DXCreateTextureFromFileEx(device, L"secureHackedNodeAnim.png",
			D3DX_DEFAULT_NONPOW2, D3DX_DEFAULT_NONPOW2,
			0, 0, D3DFMT_FROM_FILE, D3DPOOL_DEFAULT,
			D3DX_DEFAULT, D3DX_DEFAULT,
			0, 0, 0, &secureHackedNodeAnim[i-1]);


		// Create animation from texture & set attributes
		Animation* secureHackedNode = new Animation(secureHackedNodeAnim[i-1]);
		// Add amination to anims
		tmp[i]->addAnimation("secureHackedNodeAnim", secureHackedNode);
		

		//secureHackedNodeAnim
		D3DXCreateTextureFromFileEx(device, L"hackingNeutralNodeAnim.png",
			D3DX_DEFAULT_NONPOW2, D3DX_DEFAULT_NONPOW2,
			0, 0, D3DFMT_FROM_FILE, D3DPOOL_DEFAULT,
			D3DX_DEFAULT, D3DX_DEFAULT,
			0, 0, 0, &hackingNeutralNodeAnim[i-1]);


		// Create animation from texture & set attributes
		Animation* hackingNeutralNode = new Animation(hackingNeutralNodeAnim[i-1]);
		// Add amination to anims
		tmp[i]->addAnimation("hackingNeutralNodeAnim", hackingNeutralNode);


		//securingNeutralNodeAnim
		D3DXCreateTextureFromFileEx(device, L"securingNeutralNodeAnim.png",
			D3DX_DEFAULT_NONPOW2, D3DX_DEFAULT_NONPOW2,
			0, 0, D3DFMT_FROM_FILE, D3DPOOL_DEFAULT,
			D3DX_DEFAULT, D3DX_DEFAULT,
			0, 0, 0, &securingNeutralNodeAnim[i-1]);


		// Create animation from texture & set attributes
		Animation* securingNeutralNode = new Animation(securingNeutralNodeAnim[i-1]);
		// Add amination to anims
		tmp[i]->addAnimation("securingNeutralNodeAnim", securingNeutralNode);

		node[i] = new Node(tmp[i], nodePositions[i], Node::NEUTRAL);
	
	}


	//n -2 is target
	{
		// Create player animation pointer
		int limit = ALLNODES-2; 
		tmp[limit] = new AnimationPlayer();
	
		// Load player finishBaseIdleAnim texture
		D3DXCreateTextureFromFileEx(device, L"finishBaseIdleAnim.png",
			D3DX_DEFAULT_NONPOW2, D3DX_DEFAULT_NONPOW2,
			0, 0, D3DFMT_FROM_FILE, D3DPOOL_DEFAULT,
			D3DX_DEFAULT, D3DX_DEFAULT,
			0, 0, 0, &finishBaseIdleAnim);


		// Create animation from texture & set attributes
		Animation* finishBaseIdle = new Animation(finishBaseIdleAnim);
		// Add amination to anims
		tmp[limit]->addAnimation("finishBaseIdleAnim", finishBaseIdle);

		// Load player hackingFinishBaseAnim texture
		D3DXCreateTextureFromFileEx(device, L"hackingFinishBaseAnim.png",
			D3DX_DEFAULT_NONPOW2, D3DX_DEFAULT_NONPOW2,
			0, 0, D3DFMT_FROM_FILE, D3DPOOL_DEFAULT,
			D3DX_DEFAULT, D3DX_DEFAULT,
			0, 0, 0, &hackingFinishBaseAnim);


		// Create animation from texture & set attributes
		Animation* hackingFinishBase = new Animation(hackingFinishBaseAnim);
		// Add amination to anims
		tmp[limit]->addAnimation("hackingFinishBaseAnim", hackingFinishBase);

		
		// Load player hackingFinishBaseAnim texture
		D3DXCreateTextureFromFileEx(device, L"hackedFinishBaseAnim.png",
			D3DX_DEFAULT_NONPOW2, D3DX_DEFAULT_NONPOW2,
			0, 0, D3DFMT_FROM_FILE, D3DPOOL_DEFAULT,
			D3DX_DEFAULT, D3DX_DEFAULT,
			0, 0, 0, &hackedFinishBaseAnim);


		// Create animation from texture & set attributes
		Animation* hackedFinishBase = new Animation(hackedFinishBaseAnim);
		// Add amination to anims
		tmp[limit]->addAnimation("hackedFinishBaseAnim", hackedFinishBase);


		node[limit] = new Node(tmp[limit], nodePositions[limit], Node::FINISH);

	}

	//Set up opponent node
	{
		// Create player animation pointer
		int limit = ALLNODES-1;
		tmp[limit] = new AnimationPlayer();
	
		// Load player idle texture
		D3DXCreateTextureFromFileEx(device, L"enemyBaseIdleAnim.png",
			D3DX_DEFAULT_NONPOW2, D3DX_DEFAULT_NONPOW2,
			0, 0, D3DFMT_FROM_FILE, D3DPOOL_DEFAULT,
			D3DX_DEFAULT, D3DX_DEFAULT,
			0, 0, 0, &enemyBaseIdleAnim);


		// Create animation from texture & set attributes
		Animation* enemyBaseIdle = new Animation(enemyBaseIdleAnim);
		// Add amination to anims
		tmp[limit]->addAnimation("enemyBaseIdleAnim", enemyBaseIdle);
		
		//playerBaseActiveAnim
		D3DXCreateTextureFromFileEx(device, L"enemyBaseActiveAnim.png",
			D3DX_DEFAULT_NONPOW2, D3DX_DEFAULT_NONPOW2,
			0, 0, D3DFMT_FROM_FILE, D3DPOOL_DEFAULT,
			D3DX_DEFAULT, D3DX_DEFAULT,
			0, 0, 0, &enemyBaseActiveAnim);


		// Create animation from texture & set attributes
		Animation* enemyBaseActive = new Animation(enemyBaseActiveAnim);
		// Add amination to anims
		tmp[limit]->addAnimation("enemyBaseActiveAnim", enemyBaseActive);

		node[limit] = new Node(tmp[limit], nodePositions[limit], Node::ENEMY);

	}
	AnimationPlayer* cursorAnims = new AnimationPlayer();
	
	// Load animations and setup Player entity.
	{
		// Load idle cursor texture
		D3DXCreateTextureFromFileEx(device, L"playerIdleAnim.png",
			D3DX_DEFAULT_NONPOW2, D3DX_DEFAULT_NONPOW2,
			0, 0, D3DFMT_FROM_FILE, D3DPOOL_DEFAULT,
			D3DX_DEFAULT, D3DX_DEFAULT,
			0, 0, 0, &playerIdleAnim);
		// Create animation from texture
		Animation* playerIdle = new Animation(playerIdleAnim);
		// Add animation to player
		cursorAnims->addAnimation("Idle", playerIdle);
		// Load rotarting cursor texture
		D3DXCreateTextureFromFileEx(device, L"playerCursorAnim.png",
			D3DX_DEFAULT_NONPOW2, D3DX_DEFAULT_NONPOW2,
			0, 0, D3DFMT_FROM_FILE, D3DPOOL_DEFAULT,
			D3DX_DEFAULT, D3DX_DEFAULT,
			0, 0, 0, &playerCursorAnim);
		// Create animation for texture
		Animation* playerCursor = new Animation(playerCursorAnim);
		// Add to Animation player
		cursorAnims->addAnimation("Focus", playerCursor);
		// Load target cursor texture
		D3DXCreateTextureFromFileEx(device, L"playerTargetAnim.png",
			D3DX_DEFAULT_NONPOW2, D3DX_DEFAULT_NONPOW2,
			0, 0, D3DFMT_FROM_FILE, D3DPOOL_DEFAULT,
			D3DX_DEFAULT, D3DX_DEFAULT,
			0, 0, 0, &playerTargetAnim);
		// Create animation from texture
		Animation* playerTarget = new Animation(playerTargetAnim);
		// Add animation to player
		cursorAnims->addAnimation("Target", playerTarget);

		
	}

	//add linking of nodes
	
	//adding id 1 to id 0 - always zero player
	links[0].push_back(node[1]);
	
	//adding id 0, 2 and 3 to 1
	links[1].push_back(node[0]);
	links[1].push_back(node[2]);
	links[1].push_back(node[3]);
	
	//adding id 4 and 1 to 2
	links[2].push_back(node[4]);
	links[2].push_back(node[1]);

	//adding id 4 and 1 to 3
	links[3].push_back(node[4]);
	links[3].push_back(node[1]);

	//adding id 2 to 5 - last element enemy
	links[ALLNODES - 1].push_back(node[2]);
	
	for(int i = 0; i < ALLNODES; i++)
	{
		node[i]->addConnectedNodes(&links[i]);
	}

	// Create the player entity
	player = new Player(cursorAnims, node[0]);
}

void Game::unloadContent()
{
	//Need to update that later on

}

void Game::update(float frameTime)
{
	// AUDIO TEST // When Space Bar is pressed play Zap sound.
	if (inputHandler->isKeyDown(DIK_Z))
		audioState.pSoundBank->Play( audioState.iZap, 0, 0, NULL );

	// When Esc is enter pause screen if it is pressed a second time exit the game.
	if (inputHandler->isKeyDown(DIK_ESCAPE) && !inputHandler->wasKeyDown(DIK_ESCAPE) && stateMachine.getCurrentState() == stateMachine.getState("Play"))
		stateMachine.changeState("Pause");
	else if (inputHandler->isKeyDown(DIK_ESCAPE) && !inputHandler->wasKeyDown(DIK_ESCAPE) && stateMachine.getCurrentState() == stateMachine.getState("Pause"))
		PostQuitMessage(0);
	
	// Update StateMachine and hence managers, dependant on game state.
	stateMachine.update(frameTime);

	// Check for input.
	inputHandler->poll();
	// Make sounds.
	audioState.pEngine->DoWork();
}

void Game::render()
{	
	// Turn on ambient lighting.
//	device->SetRenderState(D3DRS_AMBIENT, 0xffffffff);

	// Clear buffers ready to render next frame.
	device->Clear(0, NULL, D3DCLEAR_TARGET,
				  D3DCOLOR_ARGB(0, 0, 0, 0), 1.0f, 0);
	
	device->BeginScene();
	sprite->Begin(D3DXSPRITE_ALPHABLEND);
//------Begin scene-------------------------------------------------------------

	// DRAW STUFF...
	stateMachine.draw(sprite);

//------End scene---------------------------------------------------------------
	sprite->End();
	device->EndScene();
	// Draw to back buffer & screen.
	device->Present(0, 0, 0, 0);
}